#ifndef IMAGEDOCUMENT_H
#define IMAGEDOCUMENT_H

#include <opencv/cv.h>
#include <QVector>
#include <QThread>

typedef QVector<cv::Mat> Paragraph;

class ParseThread;
struct Line
{
  int type; // 0 : seperator, 1 : line
  int start, end;
  QVector<cv::Rect> chars;
  Line(int type_ = 0, int start_ = 0, int end_ = 0) : type(type_), start(start_), end(end_) {}
};

class ImageDocument
{
  ParseThread *m_thread;
  QVector<Line> m_lines;
  int m_curLine, m_curChar;
public:
  ImageDocument();

  ParseThread* parseImage(const cv::Mat& img);
  ParseThread* createThread(const cv::Mat& img);
  void parseImage();
  QVector<Line>& lines() { return m_lines; }
  void resetCurrent() { m_curLine = 0; m_curChar = 0; }
  void moveCurrent(int d);
  int curLine() const { return m_curLine; }
  int curChar() const { return m_curChar; }
  void setCurLine(int l) { m_curLine = l; }
  void setCurChar(int c) { m_curChar = c; }
  cv::Rect curRect() const {
    return (m_curLine >= 0 && m_curLine < m_lines.size()
            && m_curChar >= 0 && m_curChar < m_lines[m_curLine].chars.size()) ?
        m_lines[m_curLine].chars[m_curChar] : cv::Rect(0, 0, 0, 0);
  }
  bool atEnd() const {
    return (m_curLine == m_lines.size()-1 && m_curChar == m_lines[m_curLine].chars.size()-1);
  }
};

class ParseThread : public QThread
{
  Q_OBJECT
signals:
  void parseLine(int);
  void detectSeparator(int, int);
  void detectLine(int, int);
  void detectParagraph(int, int);
  void detectCharacter(int, int, int, int);
public:
  ParseThread(ImageDocument* imgDoc, const cv::Mat &img);
protected:
  ImageDocument* m_imgDoc;
  const cv::Mat& m_img;

  void run();
  bool isLineEmpty(int y);
  bool isColEmpty(int x, int start, int end);
  void detectLines();
  void detectCharacters();
};

#endif // IMAGEDOCUMENT_H
